package de.hs_mannheim.vem.ajchat;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.HashMap;
import de.hs_mannheim.vem.ajchat.TcpConnection.SockOp;

public class Server {
	private static class Client {
		final String			name;
		private final long		lastaccess	= System.currentTimeMillis();
		final InetSocketAddress	address;
		final TcpConnection		con;

		Client(final String name, final InetSocketAddress address) {
			this.name = name;
			this.address = address;
			con = new TcpConnection(address);
		}
	}

	private class ServerApiImpl extends ServerApi {
		ServerApiImpl() throws IOException {
			super((InetSocketAddress) socket);
		}

		@Override
		protected void handleException(final Exception e) {
			e.printStackTrace();
		}

		@Override
		protected void receive(final ObjectInputStream ois, final SocketAddress addr) throws Exception {
			if (ois.read() == 1) {
				login(ois);
			} else {
				final String user = ois.readUTF();
				final String mess = ois.readUTF();

				// TODO Remove Debug Output
				System.out.println("Received: " + mess);

				for (final Client c : clients.values()) {
					pool.execute(new Runnable() {
						@Override
						public void run() {
							try {
								// TODO Remove Debug Output
								System.out.println("Forwarding '" + mess + "' to " + c.address);

								c.con.doSockOp(new SockOp() {
									@Override
									public void operateOnSocket(final ObjectOutputStream oos) throws Exception {
										oos.writeUTF(user);
										oos.writeUTF(mess);
									}
								});
							} catch (final Exception e) {
								handleException(e);
							}
						}
					});

				}
			}
		}
	}

	final SocketAddress				socket;
	final HashMap<String, Client>	clients	= new HashMap<String, Client>();
	ServerApi						api;

	public Server(final SocketAddress socket) {
		this.socket = socket;

		// TODO Remove Debug Output
		System.out.println("Server mit socket " + socket + " gestartet.");
	}

	public void startServer() {
		if (api != null)
			return;
		try {
			api = new ServerApiImpl();
		} catch (final IOException e) {
			e.printStackTrace();
		}
	}

	public void stopServer() {
		if (api == null)
			return;

		// TODO Remove Debug Output
		System.out.println("Server stopping ...");

		api.stopListening();
		api = null;

		// TODO Remove Debug Output
		System.out.println("Server stopped.");
	}

	@Override
	public String toString() {
		return "Server@" + socket;
	}

	void login(final ObjectInputStream ois) {
		try {
			final String clientName = ois.readUTF();

			// TODO Remove Debug Output
			System.out.println("Login " + clientName);

			clients.put(clientName, new Client(clientName, (InetSocketAddress) ois.readObject()));
		} catch (final IOException e) {
			e.printStackTrace();
		} catch (final ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}
